
package com.feib.soeasy.dao.hibernate;

import java.sql.SQLException;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.stereotype.Repository;

import com.feib.soeasy.dao.MenuItemDao;
import com.feib.soeasy.model.MenuItem;
import com.feib.soeasy.pagination.PaginatedList;


/**
 * @title (#)MenuItemHibernateDao.java<br>
 * @description <br>
 * @author Anson Tsai<br>
 * @version 1.0.0 2010/11/25
 * @copyright Far Eastern International Bank Copyright (c) 2010<br>
 * @2010/12/4 create by Anson Tsai<br>
 */
@Repository("menuItemDao")
public class MenuItemHibernateDao extends BaseHibernateDao<MenuItem, Long> implements MenuItemDao {
    
    /* (non-Javadoc)
     * @see com.feib.soeasy.dao.hibernate.BaseHibernateDao#findAll()
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<MenuItem> findAllMenuItemLazyRoles() {
        return getHibernateTemplate().executeFind(new HibernateCallback()
        {

            public List<MenuItem> doInHibernate(Session session)
            throws HibernateException, SQLException
            {
                Criteria crit = session.createCriteria(getPersistentClass());
                crit.setFetchMode("roles", FetchMode.JOIN);
                return crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
                .list();
            }
        });
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<MenuItem> findAllOrderMenuId() {
        
        StringBuffer hql = new StringBuffer();
        hql.append("from MenuItem where enabled = true ");
        hql.append("order by menuId, orderNo ");

        List<MenuItem> list = getSession().createQuery(hql.toString()).list();
        
        return list;
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public List<MenuItem> findSchoolOrderMenuId() {
        
        StringBuffer hql = new StringBuffer();
        hql.append("from MenuItem where enabled = true and school = true ");
        hql.append("order by menuId, orderNo ");

        List<MenuItem> list = getSession().createQuery(hql.toString()).list();
        
        return list;
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public List<MenuItem> findCommitteeOrderMenuId() {
        
        StringBuffer hql = new StringBuffer();
        hql.append("from MenuItem where enabled = true and committee = true ");
        hql.append("order by menuId, orderNo ");

        List<MenuItem> list = getSession().createQuery(hql.toString()).list();
        
        return list;
    }

    @SuppressWarnings("unchecked")
    @Override
    public PaginatedList<MenuItem> queryPaginationByConditions(String menuType, String menuId, String actionName, PaginatedList<MenuItem> paginationConfig) {
        PaginatedList<MenuItem> result = new PaginatedList<MenuItem>();
        result.setPageSize(paginationConfig.getPageSize());
        result.setPageNumber(paginationConfig.getPageNumber());
        result.setSortCriterion(paginationConfig.getSortCriterion());
        result.setSortDirection(paginationConfig.getSortDirection());
        
        result.setFullListSize(super.countByDetachedCriteria(
                        createDetachedCriteriaByConditions(menuType, menuId, actionName, false)));
        
        // 筆數大於0
        if (0 < result.getFullListSize())
        {
            DetachedCriteria criteria = 
                createDetachedCriteriaByConditions(menuType, menuId, actionName, true);
            
            /* 因為是Role的 Detail, 所以要這樣寫避免 join*/
            criteria.setProjection(Projections.projectionList()
                            .add(Projections.property("menuItemPk"), "menuItemPk")
                            .add(Projections.property("menuId"), "menuId")
                            .add(Projections.property("parentMenuItem"), "parentMenuItem")
                            .add(Projections.property("actionPage"), "actionPage")
                            .add(Projections.property("enabled"), "enabled")
                            .add(Projections.property("orderNo"), "orderNo")
                            .add(Projections.property("actionBean"), "actionBean")
                            .add(Projections.property("actionName"), "actionName")
                            .add(Projections.property("school"), "school")
                            .add(Projections.property("committee"), "committee")
                            );
            
            criteria.setResultTransformer(Transformers.aliasToBean(this.getPersistentClass()));

            //排序
            if (null != paginationConfig.getSortCriterion())
            {
                // 由小到大
                if (PaginatedList.SORT_DIRECTION_ASC == paginationConfig.getSortDirection())
                {
                    criteria.addOrder(Order.asc(paginationConfig.getSortCriterion()));
                }
                else // 由大到小
                {
                    criteria.addOrder(Order.asc(paginationConfig.getSortCriterion()));
                }
            }

            int maxResults = result.getPageSize(); //the maximum number of results
            int firstResult = result.getFirstIndexForCurrentPage();  //the first result to retrieve, numbered from 0
            result.setPaginatedList(this.getHibernateTemplate().findByCriteria(criteria, firstResult, maxResults));
        }

        return result;
    }

    protected DetachedCriteria createDetachedCriteriaByConditions(String menuType, String menuId, String actionName, boolean orderby)
    {
        DetachedCriteria criteria = DetachedCriteria.forClass(this.getPersistentClass());
        criteria.setResultTransformer(DetachedCriteria.DISTINCT_ROOT_ENTITY);
        
        if ("0".equals(menuType))
        {
            criteria.add(Restrictions.isNull("parentMenuItem"));
        }
        else
        {
            criteria.add(Restrictions.isNotNull("parentMenuItem"));
        }
        
        if ( StringUtils.isNotBlank(menuId))
        {
            criteria.add(Restrictions.like("menuId", menuId, MatchMode.START));
        }
        
        if ( StringUtils.isNotBlank(actionName))
        {
            criteria.add(Restrictions.like("actionName", actionName, MatchMode.START));
        }
        
        if (orderby)
            criteria.addOrder(Order.asc("menuId"));
        
        return criteria;
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<MenuItem> findParentMenuItem() {
        StringBuffer hql = new StringBuffer();
        hql.append("from MenuItem where parentMenuItem is null ");
        hql.append("order by menuId ");

        List<MenuItem> list = getSession().createQuery(hql.toString()).list();
        
        return list;
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public List<MenuItem> getNoneBankAdminMenu() {
        
        StringBuffer hql = new StringBuffer();
        hql.append("from MenuItem where menuId in ('SOEZ9000', 'SOEZ9001', 'SOEZ9002', 'SOEZ9006', 'SOEZ9010' , 'SOEZ9011' , 'SOEZ9012') ");
        
        List<MenuItem> list = getSession().createQuery(hql.toString()).list();
        
        return list;
    }
}
